/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package minesweeper.components;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JComponent;
import minesweeper.components.sectorneighbor.NeighborEvent;
import minesweeper.components.sectorneighbor.NeighborListener;
import minesweeper.gameaction.GameActionEvent;
import minesweeper.gameaction.GameActionListener;
import minesweeper.gameaction.GameActionType;
import minesweeper.gameover.GameOverEvent;
import minesweeper.gameover.GameOverListener;
import minesweeper.util.Constants;

/**
 *
 * @author Cj
 */
public class Sector extends JComponent implements MouseListener, GameOverListener,
        NeighborListener{
    
    protected ArrayList<GameActionListener> gameActionListeners;
    protected ArrayList<Sector> neighbors;
    
    protected boolean revealed;
    protected boolean highlighted;
    protected boolean flagged;
    protected boolean bomb;
    
    protected int numSurroundingBombs;

    public Sector(boolean bomb, int px_width, int px_height, int numSurroundingBombs){
        this.gameActionListeners = new ArrayList<GameActionListener>();
        this.neighbors = new ArrayList<Sector>();
        
        this.bomb = bomb;
        this.numSurroundingBombs = numSurroundingBombs;

        this.revealed = false;
        this.highlighted = false;
        this.flagged = false;

        this.addMouseListener(this);
        this.setPreferredSize(new Dimension(px_width, px_height));
        this.setVisible(true);
    }
    
    public void addGameActionListener(GameActionListener listener){
        this.gameActionListeners.add(listener);
    }
    
    private void notifyGameActionListeners(GameActionType type){
        GameActionEvent e = new GameActionEvent(this, type);
        for(int i = 0; i < this.gameActionListeners.size(); ++i){
            this.gameActionListeners.get(i).gameActionPerformed(e);
        }
    }
    
    public boolean revealed(){
        return this.revealed;
    }
    
    public boolean bomb(){
        return this.bomb;
    }
    
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Dimension dim = this.getPreferredSize();
        int px_width = (int)dim.getWidth();
        int px_height = (int)dim.getHeight();

        //Fill with white
        g.setColor(Constants.SECTOR_BACKGROUND_COLOR);
        g.fillRect(0, 0, px_width, px_height);

        //Draw Center
        if(this.revealed){
            if(this.bomb){
                //Draw Bomb
                g.setColor(Color.BLACK);
                g.fillOval(0, 0, px_width, px_height);
            }else{
                //Draw Number
                int center_x = px_width/2;
                int center_y = px_height/2;
                int location_x = (int)(center_x * 0.5);
                int location_y = (int)(center_y * 1.5);
                g.setColor(Color.BLACK);
                g.drawString(""+this.numSurroundingBombs, location_x, location_y);
            }
        }else{
            //Fill with unrevealed color
            g.setColor(Constants.SECTOR_UNREVEALED_COLOR);
            g.fillRect(0, 0, px_width, px_height);
        }
        
        //Draw Border, should be rendered twice
        if(this.highlighted){
            g.setColor(Constants.SECTOR_HIGHLIGHTED_COLOR);
        }else{
            g.setColor(Constants.SECTOR_DIVISION_COLOR);
        }
        g.drawRect(0, 0, px_width, px_height);
        
        //Draw Flagged
        if(this.flagged){
            //Draw Diagonal
            g.setColor(Constants.SECTOR_FLAGGED_COLOR);
            g.drawLine(0, 0, px_width, px_height);
            g.drawLine(px_width, 0, 0, px_height);
        }
    }
    
    public void mouseEntered(MouseEvent e) {
        this.highlighted = true;
    }

    public void mouseExited(MouseEvent e) {
        this.highlighted = false;
    }
    
    public void mouseClicked(MouseEvent e){
        System.out.println("Input Mouse Caught: #" + e.getButton());
        if(!this.revealed){
            if(e.getButton() == 1 && !this.flagged){
                this.revealed = true;
                if(this.bomb){
                    this.notifyGameActionListeners(GameActionType.BOMB_SECTOR_SELECTED);
                }else{
                    this.notifyGameActionListeners(GameActionType.SAFE_SECTOR_SELECTED);
                    this.neighborRevealed(new NeighborEvent(this));
                }
            }else if(e.getButton() == 3){
                if(this.flagged)
                    this.notifyGameActionListeners(GameActionType.UNFLAGGED_SECTOR);
                else
                    this.notifyGameActionListeners(GameActionType.FLAGGED_SECTOR);
                this.flagged = !this.flagged;
            }
        }
    }

    public void mousePressed(MouseEvent e) {    }

    public void mouseReleased(MouseEvent e) {    }

    public void gameOverTriggered(GameOverEvent e){
        //If GameOVer is Triggered, reveal self
        this.revealed = true;
    }
    
    public void addNeighborListener(Sector sector){
        this.neighbors.add(sector);
    }
    
    private void notifyNeighborListeners(){
        for(Sector neighbor: this.neighbors){
            if(!neighbor.revealed){
                neighbor.neighborRevealed(new NeighborEvent(this));
            }
        }
    }

    private void revealSurrounding(){
        for(Sector neighbor: this.neighbors){
            neighbor.revealed = true;
        }
    }
    
    public void neighborRevealed(NeighborEvent e){
        if(this.numSurroundingBombs == 0){
            this.revealed = true;
            this.notifyNeighborListeners();
            this.revealSurrounding();
        }
    }
}
